package top.yinjinbiao.demo.netty.custom.spdpa;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.MessageToMessageEncoder;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Description TODO
 * @Author yin.jinbiao
 * @Date 2021/11/4 9:43
 * @Version 1.0
 */
public class SpdpaSender {
    private static int S_PORT = 10010; //Sender的端口
    private static int R_PORT = 10060; //Reciever的端口
    //目的地址
    private static InetSocketAddress remoteAddress = new InetSocketAddress("132.232.103.192", R_PORT);

    public static void main(String[] args) {
        //1.NioEventLoopGroup是执行者，也是线程池，线程池中初始化两个线程
        NioEventLoopGroup group = new NioEventLoopGroup(2);
        //2.启动器
        Bootstrap bootstrap = new Bootstrap();
        //3.配置启动器
        bootstrap.group(group)                         //3.1指定group
                .channel(NioDatagramChannel.class)     //3.2指定channel
                .remoteAddress(remoteAddress)          //3.3指定目的地址
                .handler(new ChannelInitializer<NioDatagramChannel>() {
                    @Override
                    protected void initChannel(NioDatagramChannel nioDatagramChannel) throws Exception {
                        //3.4在pipeline中加入编码器
                        nioDatagramChannel.pipeline().addLast(new SpdpaUdpEncoder()).addLast(new SpdpaUdpDecoder());
                    }
                });
        try {
            //4.bind并返回一个channel
            Channel channel = bootstrap.bind(S_PORT).sync().channel();


            //从线程池中取一个线程，每隔两秒发送一个报文
            ScheduledFuture future = group.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    //5.发送数据
                    String command = "AA5561000000000041646D696E";
                    channel.writeAndFlush(command);
                }
            }, 10, 60, TimeUnit.SECONDS);

            //6.等待channel的close
            channel.closeFuture().sync();
            //7.关闭group
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }
    }

    //编码器，将要发送的消息封装到一个DatagramPacket中
    private static class SpdpaUdpEncoder extends MessageToMessageEncoder<String> {
        @Override
        protected void encode(ChannelHandlerContext channelHandlerContext, String msg, List<Object> list) throws Exception {
            ByteBuf byteBuf = Unpooled.copiedBuffer(Hex2ByteUtils.hexToByteArray(msg));
            DatagramPacket packet = new DatagramPacket(byteBuf, remoteAddress);
            list.add(packet);
        }
    }

    private static class SpdpaUdpDecoder extends MessageToMessageDecoder<DatagramPacket> {
        @Override
        protected void decode(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket, List<Object> list) throws Exception {
            // TODO 对 datagramPacket 解码
            System.out.println(new String(ByteBufUtil.getBytes(datagramPacket.content()), Charset.forName("UTF-8")));
        }
    }

}
